package SMSGUI;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.StringTokenizer;

import SocialMediaSentiment.ReadExcel;
import SocialMediaSentiment.Wordcounter;
import SocialMediaSentiment.writeExcel;

import jxl.write.WriteException;


public class NaiveBayes {

	
	public static HashMap<Integer, Integer> NaiveBayes(HashMap<Integer, String> indexTweets) throws IOException
	{
		HashMap<Integer, String[]>[] indexNeutralChances = naiveBayesNeutralSentiment(indexTweets );
		HashMap<Integer, String[]>[] indexPosNegChances = naiveBayesPositiveNegative(indexTweets );
		
		HashMap<Integer, String[]> neutralClassifications = indexNeutralChances[0];
		HashMap<Integer, String[]> sentimentClassifications = indexNeutralChances[1];
		
		HashMap<Integer, String[]> positiveClassifications = indexPosNegChances[0];
		HashMap<Integer, String[]> negativeClassifications = indexPosNegChances[1];
		
		HashMap<Integer, Integer> indexSentimentMap = new HashMap<Integer, Integer>();
		
		Iterator<Integer> indexSentiment = (Iterator<Integer>) sentimentClassifications.keySet().iterator();
		int i = 0;
		while(indexSentiment.hasNext())
		{ 
			
			int index = indexSentiment.next();
			if(positiveClassifications.containsKey(index))
			{
				String[] positivesentimentchance = positiveClassifications.get(index);
				indexSentimentMap.put(index, Integer.parseInt(positivesentimentchance[0]));
			}
			else if(negativeClassifications.containsKey(index))
			{
				String[] negativesentimentchance = negativeClassifications.get(index);
				indexSentimentMap.put(index, Integer.parseInt(negativesentimentchance[0]));
			}
			else
			{
				indexSentimentMap.put(index, 0);
			}
		}	
		
		Iterator<Integer> indexNeutral = (Iterator<Integer>) neutralClassifications.keySet().iterator();
		while(indexNeutral.hasNext())
		{
			int index = indexNeutral.next();
			if(positiveClassifications.containsKey(index))
			{
				String[] positivesentimentchance = positiveClassifications.get(index);
				if(compareChancesNeutToSentiment( positivesentimentchance[1]))
				{
					indexSentimentMap.put(index, Integer.parseInt(positivesentimentchance[0]));
				}
			
			}
			else if(negativeClassifications.containsKey(index))
			{
				String[] negativesentimentchance = negativeClassifications.get(index);
				if(compareChancesNeutToSentiment( negativesentimentchance[1]))
				{
					indexSentimentMap.put(index, Integer.parseInt(negativesentimentchance[0]));
				}
			}
			
		}
		
		
		
		return indexSentimentMap;
		
	}
	
	public static HashMap<Integer, String[]>[] naiveBayesNeutralSentiment(HashMap<Integer, String> indexTweets) throws IOException
	{
		float[] sentimentChance = {(float) 0.715, (float) 0.285};
		HashMap<String, Float>[] wordCounts = getwordCountsZeroNonZero();
		HashMap<String, Float> wordsCountZero = wordCounts[0];
		HashMap<String, Float> wordsCountNonZero = wordCounts[1];
		HashMap<String, Float> wordsCountAll = wordCounts[2];
		HashMap<Integer, String[]> classificationZero = new HashMap<Integer, String[]>();
		HashMap<Integer, String[]> classificationNonZero = new HashMap<Integer, String[]>();
		
		float sentimentChanceZero = sentimentChance[0];
		float sentimentChanceNonZero = sentimentChance[1];
		float totalWordsZero = getTotalCount(wordsCountZero);
		float totalWordsNonZero = getTotalCount(wordsCountNonZero);
		
		Iterator<Integer> indexes = (Iterator<Integer>) indexTweets.keySet().iterator();
		while (indexes.hasNext()) {
			int index = indexes.next();
			String tweet = indexTweets.get(index);
			float posZero = getTweetPos(tweet, wordsCountZero, totalWordsZero,
					sentimentChanceZero, wordsCountAll);
			float posNonZero = getTweetPos(tweet, wordsCountNonZero,
					totalWordsNonZero, sentimentChanceNonZero, wordsCountAll);
			int classi = getClassification(posZero, posNonZero);
			String[] classichances = new String[2];
			classichances[0] = ""+classi;
			classichances[1] = ""+ posZero/(posZero+posNonZero) + " "+posNonZero/(posZero+posNonZero);
			if(classi == 0)
				classificationZero.put(index,  classichances);
			else
				classificationNonZero.put(index,  classichances);
		}
		HashMap[] classifications = new HashMap[2];
		classifications[0] = classificationZero;//classified 0 
		classifications[1] = classificationNonZero;//classified nonzero
		return classifications;
		
	}
	
	public static HashMap<Integer, String[]>[] naiveBayesPositiveNegative(HashMap<Integer, String> indexTweets) throws IOException
	{
		float[] sentimentChance = {(float) 0.5, (float) 0.5};
		HashMap<String, Float>[] wordCounts = getwordCountsPosNeg();
		HashMap<String, Float> wordsCountPositief = wordCounts[0];
		HashMap<String, Float> wordsCountNegatief = wordCounts[1];
		HashMap<String, Float> wordsCountAll = wordCounts[2];
		HashMap<Integer, String[]> classificationPositief = new HashMap<Integer, String[]>();
		HashMap<Integer, String[]> classificationNegatief = new HashMap<Integer, String[]>();
		
		float sentimentChancePositief = sentimentChance[0];
		float sentimentChanceNegatief = sentimentChance[1];
		float totalWordsPositief = getTotalCount(wordsCountPositief);
		float totalWordsNegatief = getTotalCount(wordsCountNegatief);
		
		Iterator<Integer> indexes = (Iterator<Integer>) indexTweets.keySet().iterator();
		while (indexes.hasNext()) {
			int index = indexes.next();
			String tweet = indexTweets.get(index);
			float posPositief = getTweetPos(tweet, wordsCountPositief, totalWordsPositief,
					sentimentChancePositief, wordsCountAll);
			float posNegatief = getTweetPos(tweet, wordsCountNegatief,
					totalWordsNegatief, sentimentChanceNegatief, wordsCountAll);
			// System.out.println(posPositief + " " + posNegatief);
			int classi = getClassificationposneg(posPositief, posNegatief);
			String[] classichances = new String[2];
			classichances[0] = ""+classi;
			classichances[1] = ""+ posPositief/(posPositief+posNegatief) + " "+posNegatief/(posPositief+posNegatief);
			if(classi > 0)
				classificationPositief.put(index,  classichances);
			else
				classificationNegatief.put(index,  classichances);
		
		}
		HashMap[] classifications = new HashMap[2];
		classifications[0] = classificationPositief;//classified positive
		classifications[1] = classificationNegatief;//classified negative
		return classifications;
		
	}
	private static HashMap<String, Float>[] getwordCountsZeroNonZero() throws IOException {
		HashMap[] wordCounts = new HashMap[3];
		wordCounts[0] = ReadExcel.readCounters("counterZero.xls", 0, 1);
		wordCounts[1] = ReadExcel.readCounters("counterNonZero.xls", 0, 1);
		wordCounts[2] = ReadExcel.readCounters("counterAllZeroNonZero.xls", 0, 1);
		return wordCounts;
	}
	
	private static HashMap<String, Float>[] getwordCountsPosNeg() throws IOException {
		HashMap[] wordCounts = new HashMap[3];
		wordCounts[0] = ReadExcel.readCounters("counterPositief.xls", 0, 1);
		wordCounts[1] = ReadExcel.readCounters("counterNegatief.xls", 0, 1);
		wordCounts[2] = ReadExcel.readCounters("counterAllPosNeg.xls", 0, 1);
		return wordCounts;
	}
	public static int getClassificationposneg(float Positief, float Negatief) {
		int classification = 1;
		if (Negatief > Positief)
			classification = -1;
		return classification;
	}  
	
	public static float getTotalCount(HashMap<String, Float> wordsCount)
			throws IOException {
		float total = 0;
		Iterator<String> k = (Iterator<String>) wordsCount.keySet().iterator();
		total += wordsCount.keySet().size();
		while (k.hasNext()) {
			String word = k.next();
			float count = wordsCount.get(word);
			total += count;
		}
		return total;
	}
	public static float getTweetPos(String tweet,
			HashMap<String, Float> wordsCount, float totalWords,
			float sentimentChance, HashMap<String, Float> wordsCountAll) {
		StringTokenizer tokenizer = new StringTokenizer(tweet);
		Float chance;
		float tweetPos = sentimentChance;
		// float words = tokenizer.countTokens();
		// tweetPos = 0;
		while (tokenizer.hasMoreTokens()) {
			String word = tokenizer.nextToken();
			if (wordsCountAll.keySet().contains(word)) {
				try {
					chance = (wordsCount.get(word)) / totalWords;
				} catch (NullPointerException e) {
					chance = 1 / totalWords;
				}

				// System.out.println(chance + "  " + tweetPos + "   " + word);
				tweetPos = tweetPos * chance * 1000;
			}
		}
		return tweetPos;
	}
	
	public static int getClassification(float Zero, float NonZero) {
		int classification = 0;
		if (NonZero > Zero)
			classification = 1;
		return classification;
	}
	private static boolean compareChancesNeutToSentiment(String chances) {
		StringTokenizer st = new StringTokenizer(chances," ");
		float chance1 = Float.parseFloat(st.nextToken());
		float chance2 = Float.parseFloat(st.nextToken());
		if(Math.abs(chance1-chance2) > 0.8)
		{
			return true;
		}
		return false;
	}
	
	public static void updateCounters( HashMap<Integer, String[]> wrongwrongTweets) throws WriteException, IOException {
		HashMap<String, Integer> wrongTweets = new HashMap<String, Integer>();
		Iterator<Integer> indexes = (Iterator<Integer>) wrongwrongTweets.keySet().iterator();
		while(indexes.hasNext())
		{
			int index = indexes.next();
			String[] goodstuff = wrongwrongTweets.get(index);
			wrongTweets.put(goodstuff[0], Integer.parseInt(goodstuff[1]));
		}
		HashMap<String, Float>[] wordcountZeroNonZero = getwordCountsZeroNonZero();
		HashMap<String, Float>[] wordcountPosNeg = getwordCountsPosNeg();
		
			
		Iterator<String> tweets = (Iterator<String>) wrongTweets.keySet().iterator();
		while (tweets.hasNext()) {
			HashMap<String, Float> wordCount = new HashMap<String, Float>();
			HashMap<String, Float> wordCount2 = new HashMap<String, Float>();
			String tweet = tweets.next();
			int sentiment = wrongTweets.get(tweet);
			if( sentiment == 0 )
			{
				wordCount = wordcountZeroNonZero[0];
				StringTokenizer tokenizer = new StringTokenizer(tweet, " ");
				while (tokenizer.hasMoreTokens()) {
					String word = tokenizer.nextToken();
					Float value;
					if (wordCount.containsKey(word)) {
						value = wordCount.get(word) + 1 + Math.abs(sentiment)*10;
					} else {
						value = (float) 1 + Math.abs(sentiment)*10;
					}	
					wordCount.put(word, value);
				}
				wordcountZeroNonZero[0] = wordCount;
			}
			else if( sentiment > 0 )
			{
				wordCount = wordcountZeroNonZero[1];
				StringTokenizer tokenizer = new StringTokenizer(tweet, " ");
				while (tokenizer.hasMoreTokens()) {
					String word = tokenizer.nextToken();
					Float value;
					if (wordCount.containsKey(word)) {
						value = wordCount.get(word) + 1 + Math.abs(sentiment)*10;
					} else {
						value = (float) 1 + Math.abs(sentiment)*10;
					}	
					wordCount.put(word, value);
				}
				wordcountZeroNonZero[1] = wordCount;
				wordCount2 = wordcountPosNeg[0];
				tokenizer = new StringTokenizer(tweet, " ");
				while (tokenizer.hasMoreTokens()) {
					String word = tokenizer.nextToken();
					Float value;
					if (wordCount.containsKey(word)) {
						value = wordCount.get(word) + 1 + Math.abs(sentiment)*10;
					} else {
						value = (float) 1 + Math.abs(sentiment)*10;
					}	
					wordCount.put(word, value);
				}
				wordcountPosNeg[0] = wordCount2;
			}
			else//sentiment < 0
			{
				wordCount = wordcountZeroNonZero[1];
				StringTokenizer tokenizer = new StringTokenizer(tweet, " ");
				while (tokenizer.hasMoreTokens()) {
					String word = tokenizer.nextToken();
					Float value;
					if (wordCount.containsKey(word)) {
						value = wordCount.get(word) + 1 + Math.abs(sentiment)*10;
					} else {
						value = (float) 1 + Math.abs(sentiment)*10;
					}	
					wordCount.put(word, value);
				}
				wordcountZeroNonZero[1] = wordCount;
				wordCount2 = wordcountPosNeg[1];
				tokenizer = new StringTokenizer(tweet, " ");
				while (tokenizer.hasMoreTokens()) {
					String word = tokenizer.nextToken();
					Float value;
					if (wordCount.containsKey(word)) {
						value = wordCount.get(word) + 1 + Math.abs(sentiment)*10;
					} else {
						value = (float) 1 + Math.abs(sentiment)*10;
					}	
					wordCount.put(word, value);
				}
				wordcountPosNeg[1] = wordCount2;
			}
			
		}
		createfilesZeroNonZero(wordcountZeroNonZero);
		createfilesPosNeg(wordcountPosNeg);
		
		
	}
	private static void createfilesZeroNonZero(HashMap<String, Float>[] wordsCounts) throws WriteException, IOException {
		HashMap<String, String> wordCountZeroFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountZero = wordsCounts[0];
		Iterator<String> wordsZero = (Iterator<String>) wordsCountZero.keySet().iterator();
		while(wordsZero.hasNext())
		{
			String word = wordsZero.next();
			Float count = wordsCountZero.get(word);
			wordCountZeroFile.put(word,""+count);
		}
		HashMap<String, String> wordCountNonZeroFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountNonZero = wordsCounts[1];		
		Iterator<String> wordsNonZero = (Iterator<String>) wordsCountNonZero.keySet().iterator();
		while(wordsNonZero.hasNext())
		{
			String word = wordsNonZero.next();
			Float count = wordsCountNonZero.get(word);
			wordCountNonZeroFile.put(word,""+count);
		}
		HashMap<String, String> wordCountAllFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountAll = wordsCounts[2];
		Iterator<String> wordsAll = (Iterator<String>) wordsCountAll.keySet().iterator();
		while(wordsAll.hasNext())
		{
			String word = wordsAll.next();
			Float count = wordsCountAll.get(word);
			wordCountAllFile.put(word,""+count);
		}
		writeExcel.write("counterZero.xls", wordCountZeroFile);
		writeExcel.write("counterNonZero.xls", wordCountNonZeroFile);
		writeExcel.write("counterAllZeroNonZero.xls", wordCountAllFile);
	}
	
	private static void createfilesPosNeg(HashMap<String, Float>[] wordsCounts) throws WriteException, IOException {
		HashMap<String, String> wordCountPositiefFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountPositief = wordsCounts[0];
		Iterator<String> wordsPositief = (Iterator<String>) wordsCountPositief.keySet().iterator();
		while(wordsPositief.hasNext())
		{
			String word = wordsPositief.next();
			Float count = wordsCountPositief.get(word);
			wordCountPositiefFile.put(word,""+count);
		}
		HashMap<String, String> wordCountNegatiefFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountNegatief = wordsCounts[1];		
		Iterator<String> wordsNegatief = (Iterator<String>) wordsCountNegatief.keySet().iterator();
		while(wordsNegatief.hasNext())
		{
			String word = wordsNegatief.next();
			Float count = wordsCountNegatief.get(word);
			wordCountNegatiefFile.put(word,""+count);
		}
		HashMap<String, String> wordCountAllFile = new HashMap<String, String>();
		HashMap<String, Float> wordsCountAll = wordsCounts[2];
		Iterator<String> wordsAll = (Iterator<String>) wordsCountAll.keySet().iterator();
		while(wordsAll.hasNext())
		{
			String word = wordsAll.next();
			Float count = wordsCountAll.get(word);
			wordCountAllFile.put(word,""+count);
		}
		writeExcel.write("counterPositief.xls", wordCountPositiefFile);
		writeExcel.write("counterNegatief.xls", wordCountNegatiefFile);
		writeExcel.write("counterAllPosNeg.xls", wordCountAllFile);
	}
		
	
	
}
